/*****************************************************************************//*!
* file  : systask.c
* creat : apleilx
* data  : 2017/11/05
*******************************************************************************/

#include "cs1237_dev.h"
/* 数据格式
*  正值满幅输出码为 7FFFFFH
*  负值满幅输出码为 800000H
*  1bit符号位，23bits数据位，共24bits
*/

//----------------------------------------------------------------------------

#define ADC_Bit  (obj->bits) //ADC有效位数，带符号位 最高24位

#define SCK_1 obj->sck_out(1);obj->delay_0_5us(3);
#define SCK_0 obj->sck_out(0);obj->delay_0_5us(3);
#define DAT_1 obj->dat_out(1);obj->delay_0_5us(3);
#define DAT_0 obj->dat_out(0);obj->delay_0_5us(3);

#define One_CLK  SCK_1;SCK_0

#define DAT_IN_ST()  (obj->dat_in())

#define CS_CON  0X10   //芯片地配置 内部REF 输出40HZ PGA=1 通道A

//A3 A5 A7 B1 0x76543210
#define DioInput() {\
obj->dat_dir(0);\
obj->delay_0_5us(2);\
}


#define DioOutput() {\
obj->dat_dir(1);\
obj->delay_0_5us(2);\
}

static int32_t MiddleValSearch(int32_t* Src);
/*****************************************************************************//*!
*
* @brief   reg set.//配置CS1237芯片
*
* @return  state 0-busy  1-ok
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
uint8_t cs1237_cfg_set(cs1237_type *obj, uint8_t cmd)
{
    unsigned char cnt, u8t;
    unsigned char dat;
    uint32_t datr;
    
    SCK_0;//时钟拉低
    DioInput();
    
    //芯片准备好数据输出  时钟已经为0，数据也需要等CS1237全部拉低为0才算都准备好
    
    if(DAT_IN_ST())
    {
        return 0; //not ready
    }
    
    datr = 0;
    for(cnt=0; cnt<24; cnt++) // 1 - 24
    {
        One_CLK;
        datr <<= 1;
        
        if(DAT_IN_ST())
            datr ++;
    }
    
    obj->ad_org = datr;
    
    for(; cnt<29; cnt++) // 25 - 29
    {
        One_CLK;
    }
    
    DioOutput();
    
    //write cmd
    u8t = 0x65;
    for(cnt=0;cnt<7;cnt++) //30 - 36
    {
        u8t <<= 1;
        if(u8t&0x80)
        {
            DAT_1;
        }
        else
        {
            DAT_0;
        }
        
        One_CLK;
    }
    
    One_CLK;        //37     写入了0x65
    
    dat = cmd;
    for(cnt=0; cnt<8; cnt++) // 38 - 45 //write control cmd
    {
        if(dat&0x80)
        {
            DAT_1;
        }
        else
        {
            DAT_0;
        }
        dat <<= 1;
        One_CLK; 
    }
    
    DioInput();
    One_CLK;  //46 end
    
    return 1;
}

/*****************************************************************************//*!
*
* @brief   reg read.//读取芯片的配置数据
*
* @return  state 0-busy  1-ok
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
uint8_t cs1237_cfg_read(cs1237_type *obj)
{
    unsigned char u8t;
    unsigned char cnt;
    unsigned char dat=0;//读取到的数据
    
    SCK_0;//时钟拉低
    DioInput();
    
    //芯片准备好数据输出  时钟已经为0，数据也需要等CS1237全部拉低为0才算都准备好
    if(DAT_IN_ST())
    {
        return 0;// not ready
    }
    
    //read adval clk
    for(cnt=0; cnt<29; cnt++) // 1 - 29
    {
        One_CLK;
    }
    
    DioOutput();
    
    //write cmd
    u8t = 0x56;
    for(cnt=0;cnt<7;cnt++)
    {
        u8t <<= 1;
        if(u8t&0x80)
        {
            DAT_1;
        }
        else
        {
            DAT_0;
        }
        
        One_CLK;
    }
    
    DioInput();
    One_CLK;//37     写入了0x56

    dat=0;
    for(cnt=0; cnt<8; cnt++) // 38 - 45 read cmd
    {
        One_CLK;
        
        dat <<= 1;
        
        if(DAT_IN_ST())
            dat++;
    }
    
    One_CLK;//46个脉冲拉高数据引脚
    
    obj->cfg_read = dat;
    
    return 1;
}

/*****************************************************************************//*!
*
* @brief   ad read.//读取ADC数据，返回的是一个有符号数据
*
* @return  state 0-busy  1-ok
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
uint8_t cs1237_ad_read(cs1237_type *obj)
{
    unsigned char cnt;
    uint32_t dat;//读取到的数据
    uint32_t dat_msk;
    uint8_t neg;
    
    SCK_0;//时钟拉低
    DioInput();
    
    while(DAT_IN_ST())  //芯片准备好数据输出  时钟已经为0，数据也需要等CS1237拉低为0才算都准备好
    {
        return 0;       // not ready
    }

    dat=0;
    for(cnt=0; cnt<24; cnt++) //read data
    {
        One_CLK;
        

        dat <<= 1;
        
        if(DAT_IN_ST())
            dat ++;
    }
    obj->ad_org = dat;
    
    for(cnt=24; cnt<27; cnt++) //一共输入27个脉冲
    {
        One_CLK;
    }
    
    //先根据宏定义里面的有效位，丢弃一些数据
    cnt = 24 - (ADC_Bit+1);//i表示将要丢弃的位数
    dat_msk = UINT32_MAX >> (32 - (ADC_Bit+1));
    
    if(dat & (1UL << 23)) //第24bit 为符号位
        neg = 1;
    else
        neg = 0;
    
    //丢弃多余的位数
    dat >>= cnt;
    if(neg) //负数补充高位
    {
        dat |= ~dat_msk;
    }

    if (obj->cfg_read == obj->cfg_ext)
    {
        obj->ad_buff[obj->buff_index] = dat;

        obj->buff_index++;
        if (obj->buff_index > 4)
            obj->buff_index = 0;


        obj->ad_val = MiddleValSearch(obj->ad_buff);
        obj->b_ad_val_ready = 1;
        obj->sample_ok_cnt++;
    }

    obj->ad_real = dat;

    return 1;
}

/*****************************************************************************//*!
*
* @brief   ad read.//读取ADC数据，并设定新的配置字，返回的是一个有符号数据
*
* @return  state 0-busy  1-ok
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
uint8_t cs1237_ad_read_and_set(cs1237_type *obj, uint8_t cmd)
{
    unsigned char cnt;
    uint32_t dat;//读取到的数据
    uint32_t dat_msk;
    uint8_t neg;
    uint8_t u8t;
    
    SCK_0;//时钟拉低
    DioInput();
    
    while(DAT_IN_ST())  //芯片准备好数据输出  时钟已经为0，数据也需要等CS1237拉低为0才算都准备好
    {
        return 0;       // not ready
    }

    //第 1 个到第 24 个 SCLK，读取 ADC 数据。如果不需要配置寄存器或者读取寄存器，可以省略后面的步骤。
    dat=0;
    for(cnt=1; cnt<=24; cnt++) //read data
    {
        One_CLK;
        

        dat <<= 1;
        
        if(DAT_IN_ST())
            dat ++;
    }
    obj->ad_org = dat;
    
    //第 25 个到第 26 个 SCLK，读取寄存器写操作状态。
    //第 27 个 SCLK，CS1237把 DRDY / DOUT 输出拉高。
    for(cnt=25; cnt<=27; cnt++) //一共输入27个脉冲
    {
        One_CLK;
    }
    
    //先根据宏定义里面的有效位，丢弃一些数据
    cnt = 24 - (ADC_Bit+1);//i表示将要丢弃的位数
    dat_msk = UINT32_MAX >> (32 - (ADC_Bit+1));
    
    if(dat & (1UL << 23)) //第24bit 为符号位
        neg = 1;
    else
        neg = 0;
    
    //丢弃多余的位数
    dat >>= cnt;
    if(neg) //负数补充高位
    {
        dat |= ~dat_msk;
    }

    if (obj->cfg_read == obj->cfg_ext)
    {
        obj->ad_buff[obj->buff_index] = dat;

        obj->buff_index++;
        if (obj->buff_index > 4)
            obj->buff_index = 0;


        obj->ad_val = MiddleValSearch(obj->ad_buff);
        obj->b_ad_val_ready = 1;
        obj->sample_ok_cnt++;
    }

    obj->ad_real = dat;
    
    //new cmd set
    //第 28 个到第 29 个 SCLK，CS1237切换 DRDY / DOUT 为输入。
    for(cnt=28; cnt<=29; cnt++) // 1 - 29
    {
        One_CLK;
    }
    DioOutput();
    
    //write cmd
    u8t = 0x65;
    //第 30 个到第 36 个 SCLK，输入寄存器写或读命令字数据(高位先输入)
    for(cnt=30;cnt<=36;cnt++) //30 - 36
    {
        u8t <<= 1;
        if(u8t&0x80)
        {
            DAT_1;
        }
        else
        {
            DAT_0;
        }
        
        One_CLK;
    }
    
    //第 37 个 SCLK ， 切 换 DRDY / DOUT 的 方 向
    One_CLK;        //37     写入了0x65
    
    //第 38 个到第 45 个 SCLK，输入寄存器配置数据或输出寄存器配置数据(高位先输入/输出)。
    dat = cmd;
    for(cnt=38; cnt<=45; cnt++) //38 - 45 //write control cmd
    {
        if(dat&0x80)
        {
            DAT_1;
        }
        else
        {
            DAT_0;
        }
        dat <<= 1;
        One_CLK; 
    }
    
    //第 46 个 SCLK，切换 DRDY/ DOUT 为输出，并把 DRDY/ DOUT 拉高。
    DioInput();
    One_CLK;  //46 end
    
    return 1;
}

/*****************************************************************************//*!
*
* @brief   middle val search Len = 5
*            
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
static int32_t MiddleValSearch(int32_t* Src){
    uint8_t Index;
    uint8_t i;
    uint8_t j;    
    
    int32_t data[5];
    int32_t temp;

    Index = 5;
    while(Index--)
        data[Index] = Src[Index];
    
    for (j = 0; j < (5 - 1); j++)
    {
        for (i = 0; i < (5 - 1 - j); i++)
        {
            if(data[i] > data[i + 1])
            {
                temp = data[i];
                data[i] = data[i + 1];
                data[i + 1] = temp;
            }
        }
    }
    
    return data[2];
}

